#[macro_use]
extern crate serde_derive;
extern crate serde;

use data::*;
use local_time::*;
use std::error::Error;
use trade::*;

fn main() -> Result<(), Box<dyn Error>> {
    let earn = back_testing()?;
    println!("back_testing 的结果是：{}", earn);

    Ok(())
}

pub fn back_testing() -> Result<isize, Box<dyn Error>> {
    // 初始化成交数据
    let tran_datas = TransactionDatas::new()?;
    // 初始化报价数据
    let tick_datas = TickDatas::new()?;
    // 初始化账户信息
    let mut account = Account::new();
    // 每次买入的股票数量
    const STOCK_NUM: usize = 1000;

    let (start_mapping, end_mapping) = tran_datas.build_tran_mapping();

    for cur in (TimeRange { start: 93000 }) {
        let mut start = sub_10_minus(cur)?;

        // 可用一个mapping存储start_index和end_index
        let mut start_index = start_mapping.get(&start);
        // 如果开市时间的秒数里没有报价，向后找
        while start_index == None {
            start = cal_time_s(start, 1, CalType::ADD);
            start_index = start_mapping.get(&start);
        }
        // 当前时间没有报价，跳过此次循环
        let end_index = end_mapping.get(&cur);
        if end_index == None {
            continue;
        }

        let tran_cur = &tran_datas.datas[*end_index.unwrap()];

        // 个股在【10min】内上涨【0.5%】以上（包含），进行一次【市价委托】买入操作，买入数量为【1000】股，连续两次买入操作间隔需大于30秒
        if account.satisfy_buy_time(tran_cur.time) {
            let tran_min = tran_datas.datas[*start_index.unwrap()..=*end_index.unwrap()]
                .iter()
                .min()
                .unwrap();

            if tran_cur.get_percent(&tran_min) >= 0.005_f32 {
                let tick_cur = tick_datas.pick_after_time(tran_cur.time)?;
                let ask_info_10 = tick_cur.ask_info_10();
                account.market_price_buy(&ask_info_10, STOCK_NUM);

                // 在60s后对该笔进行卖出操作
                let passive_sell_time = cal_time_ms(tran_cur.time, 60_000, CalType::ADD);
                let ask_info_10_passive = tick_datas.pick_after_time(passive_sell_time)?;
                let ask_price_passive = ask_info_10_passive.ask_info_10().info_1_vec[0].price;
                let remanent_volume = account.passive_sell(
                    ask_price_passive,
                    STOCK_NUM,
                    passive_sell_time,
                    &tick_datas,
                );

                // 如果30s后没有全部成交，则以市价委托卖出
                if remanent_volume != 0 {
                    let market_price_sell_time =
                        cal_time_ms(passive_sell_time, 30_000, CalType::ADD);
                    let bid_info_10 = tick_datas
                        .pick_after_time(market_price_sell_time)?
                        .bid_info_10();
                    account.market_price_sell(&bid_info_10, remanent_volume);
                }
            }
        }
    }

    Ok(account.funds)
}

mod data;
mod local_time;
mod trade;
